public void RecompressData(){
 //Chrono Trigger Recompression Routine
 //Reverse engineered by Michael Springer (evilpeer@hotmail.com)
 ushort j;
 ushort k;
 byte i;
 byte nBitCtr; // Bit counter used for construction of Packet Header
 ushort nOffset; // Byte offset in uncompressed data of pattern (counting backwards from current position)
 ushort nCopyLength; // Number of bytes to copy when uncompressing
 uint nSrcPos; // Byte position in uncompressed (source) data
 ushort nWorkPos; // Byte position in compressed data
 ushort nPackHdrOff; // Packet Header, constructed as source data is read
 byte[][] CompData = new byte[2][];
 ushort nCompSize = 0xFFFF;
 ushort nArrLength = 0; // Final data length
 ushort nRange;  // The maximum range is either 0x0FFF or 0x07FF
 byte nMaxCopy;  // The maximum number of bytes to copy is either 18 or 34

 // External class variables, set by calling function. May or may not be used
 // uint nSrcOff;  // Source starting offset
 // uint nWorkOff;  // Destination array starting offset
 // uint nCompressedSize;
 // uint nDecompressedSize;
 // byte[] WorkingBuffer; // Destination array
 // byte[] SrcBuffer;  // Source array

 for(i = 0; i < 2; i++){
 nRange = (ushort) (0x07FF | (i << 11));
 nMaxCopy = (byte) (18 + ((1 - i) << 4));
 nSrcPos = 1;
 nBitCtr = 1;
 nOffset = 0;
 nCopyLength = 0;
 nWorkPos = 4;
 nPackHdrOff = 2;
 CompData[i] = new byte[0x10000];
 CompData[i][3] = SrcBuffer[nSrcOff];
 
			while(nSrcPos < nDecompressedSize && nWorkPos < nCompSize){
				for(; nBitCtr < 8 && nSrcPos < nDecompressedSize; nBitCtr++){
					if(nSrcPos > nRange){
						j = (ushort) (nSrcPos - nRange);
					}
					else{
						j = 0;
					}
					for(; j < nSrcPos; j++){
						for(k = 0; k < nMaxCopy && SrcBuffer[nSrcOff + j + k] == SrcBuffer[nSrcOff + nSrcPos + k]; k++){
						}

						if(k >= nCopyLength){
							nOffset = j;
							nCopyLength = k;
							if(k == nMaxCopy){
								break;
							}
						}
					}
					if(nCopyLength > 2){
						CompData[i][nPackHdrOff] |= (byte) (1 << nBitCtr);
						nOffset = (ushort) (nSrcPos - nOffset);
						CompData[i][nWorkPos++] = (byte) (nOffset & 0xFF);
						CompData[i][nWorkPos++] = (byte) (((nCopyLength - 3) << (3 + i)) | ((nOffset >> 8) & (0x07 | (i << 3))));
						nSrcPos += nCopyLength;
						nCopyLength = 0;
					}
					else{
						CompData[i][nWorkPos++] = SrcBuffer[nSrcOff + nSrcPos++];
					}
				}
				if(nBitCtr == 8){
					nBitCtr = 0;
					nPackHdrOff = nWorkPos;
					nWorkPos++;
				}
			}

			if(nWorkPos < nCompSize){
				if(nBitCtr > 0){
					CompData[i][nPackHdrOff] |= (byte) (0xFF << nBitCtr);
					Array.Copy(CompData[i], nPackHdrOff, CompData[i], nPackHdrOff + 3, nWorkPos - nPackHdrOff);
					CompData[i][nPackHdrOff] = (byte) (nBitCtr | (0xC0 * (i - 1)));
					nArrLength = (ushort) (nWorkPos + 3);
					CompData[i][nPackHdrOff + 1] = (byte) nArrLength;
					CompData[i][nPackHdrOff + 2] = (byte) (nArrLength >> 8);
					CompData[i][nWorkPos + 3] = 0;
				}
				else{
					nArrLength = (ushort) (nPackHdrOff + 1);
					CompData[i][nPackHdrOff] = (byte) (0xC0 * (i - 1));
				}

				nCompSize = (ushort) (nPackHdrOff - 2);
				CompData[i][0] = (byte) (nCompSize & 0xFF);
				CompData[i][1] = (byte) (nCompSize >> 8);

				Array.Copy(CompData[i], 0, WorkingBuffer, nWorkOff, nArrLength + 1);
				nCompressedSize = (uint) (nArrLength + 1);
			}
		}
	}
}

